package twitter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class Downloader {
	URL url;
	/**
	 * Download a content of a url
	 * @param url The target to download
	 */
	public Downloader(URL url) {
		this.url = url;
	}
	
	/**
	 * Fetch and return content of url as String
	 * @return String String result of content
	 */
	public String fetchAsString() {
		int failed = 0;
		int blockedDeep = 0;
		while(failed < 3) {
			try {
				URLConnection connection = getURLConnection();
				int status = ((HttpURLConnection) connection).getResponseCode();
				int contentLength = ((HttpURLConnection) connection).getContentLength();
				if(status == 502) {
					System.err.println("Refused: Twitter.com refused to give content.");
					return "_exeption_refused";
				}
				
				// We do not download file with too big size
				if(contentLength > 400000) { // 2581684
					System.err.println("Aborted: Content-Length too long");
					return "_exeption_aborted";
				}
				
				// Blocked
				if(status == 400) {
					blockedDeep++;
					
					if(blockedDeep >= 5) {
						System.err.println("Blocked: Client was blocked by twitter");
						blockedDeep = 0;
						return "_exeption_blocked";
					}
					else {
						Helper.log("Blocked? Retry "+ blockedDeep);
						continue;
					}
				}
				
				// 
				if(status == 401) {
					System.err.println("Protected: Twitter profile is protected");
					return "_exeption_protected";
				}
				
				// We go only futher if received success code
				if(status != 200) {
					failed++;
					System.err.println("Failed: Failed to get content. ResponseCode "+ status);
					if(failed <= 0) {
						return "_exeption_failed";
					}
					else {
						System.err.println("Retry "+ failed);
						continue;
					}
				}
				
				// Update traffic
				Client.setTraffic(contentLength);
			    
			    String string = convertStreamToString(connection.getInputStream());
			    
			    return string;
			} catch (IOException e) {
				failed++;
				System.err.println("IOException on Downloader.java. Retry "+ failed);
			}
		}

		return null;
	}
	
	/**
	 * Convert a Stream to String
	 * @param is
	 * @return
	 * @throws IOException 
	 * @throws Exception
	 */
	public static String convertStreamToString(InputStream is) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();
		String line = null;
		while ((line = reader.readLine()) != null) {
			sb.append(line + "\n");
		}
		is.close();
		return sb.toString();
	}

	private URLConnection getURLConnection() {
		URLConnection connection = null;
		try {
			connection = url.openConnection();
			connection.setAllowUserInteraction(false);
			connection.setDoOutput(true);
			
			// Bypass 150-limit
			modifyHeader(connection);
			
		    // OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
			// writer.write(params);
			// writer.flush();
			
		    // writer.close();
		} catch (IOException e) {
			System.err.println("IOException on Downloader.java > getURLConnection()");
		}
		
		return connection;
	}
	
	public InputStream fetchAsStream() {
		URLConnection connection = getURLConnection();
		InputStream input = null;
		try {
			input = connection.getInputStream();
		} catch (IOException e) {
			System.err.println("IOException on Downloader.java > fetchAsStream()");
		}
	    return input;
	}
	
	/**
	 * We are firefox!
	 */
	private void modifyHeader(URLConnection connection) {
		connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.5 Safari/534.30");
		connection.addRequestProperty("Accept","application/json, text/javascript, */*");
		connection.addRequestProperty("Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.3");
		connection.addRequestProperty("Accept-Language","en-US,en;q=0.8");
		connection.addRequestProperty("Connection","keep-alive");
		connection.addRequestProperty("Content-Type","application/x-www-form-urlencoded");
		connection.addRequestProperty("Host","api.twitter.com");
		connection.addRequestProperty("Referer","http://api.twitter.com/receiver.html");
		connection.addRequestProperty("X-PHX","true");
		connection.addRequestProperty("X-Requested-With","XMLHttpRequest");
	}
}
